package com.ruoyi.web.wx.controller;

import com.ruoyi.bankcardtable.domain.BankCardTable;
import com.ruoyi.bankcardtable.service.BankCardTableService;
import com.ruoyi.bankinfo.domain.BankInfo;
import com.ruoyi.bankinfo.service.IBankInfoService;
import com.ruoyi.city.domain.City;
import com.ruoyi.city.service.ICityService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.descriptionrule.domain.DescriptionRule;
import com.ruoyi.descriptionrule.service.IDescriptionRuleService;
import com.ruoyi.disease.domain.Disease;
import com.ruoyi.disease.service.IDiseaseService;
import com.ruoyi.doctorlibrary.domain.DoctorLibrary;
import com.ruoyi.doctorlibrary.domain.vo.DoctorLibraryVO;
import com.ruoyi.doctorlibrary.service.IDoctorLibraryService;
import com.ruoyi.evaluate.domain.Evaluate;
import com.ruoyi.evaluate.service.IEvaluateService;
import com.ruoyi.hospital.domain.Hospital;
import com.ruoyi.hospital.service.IHospitalService;
import com.ruoyi.questionnaire.domain.Questionnaire;
import com.ruoyi.questionnaire.service.IQuestionnaireService;
import com.ruoyi.suggestion.domain.Suggestion;
import com.ruoyi.suggestion.service.ISuggestionService;
import com.ruoyi.user.domain.User;
import com.ruoyi.user.domain.vo.ExpertLoginVO;
import com.ruoyi.user.domain.vo.ExpertPwd;
import com.ruoyi.user.domain.vo.UserVO;
import com.ruoyi.user.service.IUserService;
import com.ruoyi.withdrawaltable.domain.WithdrawalTable;
import com.ruoyi.wx.service.WxLoginService;
import com.ruoyi.wx.utils.GetUserUtils;
import com.ruoyi.wx.utils.Sha1Hex;
import com.ruoyi.wx.utils.WeChatQrCodeUtil;
import com.ruoyi.wx.vo.WxLoginVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Api(tags = "用户")
@RestController
@RequestMapping("/wx/user")
public class WxUserController {

    @Autowired
    private IUserService userService;

    @Autowired
    private BankCardTableService bankCardTableService;

    @Autowired
    private IEvaluateService evaluateService;

    @Autowired
    private ISuggestionService suggestionService;

    @Autowired
    private IDoctorLibraryService doctorLibraryService;

    @Autowired
    private IQuestionnaireService questionnaireService;

    @Autowired
    private IDiseaseService diseaseService;

    @Autowired
    private ICityService cityService;

    @Autowired
    private IHospitalService hospitalService;

    @Autowired
    private IBankInfoService bankInfoService;

    @Autowired
    private WxLoginService wxLoginService;

    @Autowired
    private IDescriptionRuleService descriptionRuleService;


    @ApiOperation("查询用户信息")
    @GetMapping("getUserByUserId")
    public AjaxResult getUserByUserId(HttpServletRequest request) {
        User user = GetUserUtils.getLoginUser(request);
        return AjaxResult.success(userService.selectUserByUserId(user.getUserId()));
    }

    @ApiOperation("获取手机验证码")
    @PostMapping("getPhoneCode")
    public AjaxResult getPhoneCode(@RequestBody ExpertLoginVO expertLoginVO) {
        userService.getPhoneCode(expertLoginVO);
        return AjaxResult.success();
    }

    @ApiOperation("专家注册")
    @PostMapping("expertRegister")
    public AjaxResult expertRegister(@RequestBody ExpertLoginVO expertLoginVO) {
        return wxLoginService.register(expertLoginVO);
    }

    @ApiOperation("专家资质申请")
    @PostMapping("expertCommit")
    public AjaxResult expertCommit(@RequestBody UserVO userVo) {
        int i = userService.insertExpertUser(userVo);
        if (i != 0) {
            return AjaxResult.success("资质提交成功");
        } else {
            return AjaxResult.error("资质提交失败, 一年内禁止超过两次");
        }
    }

    @ApiOperation("修改用户信息")
    @PostMapping("updateUser")
    public AjaxResult updateUser(@RequestBody User user) {
        return AjaxResult.success(userService.updateUser1(user));
    }

    @ApiOperation("上传头像")
    @PostMapping("avatar")
    public AjaxResult uploadAvatar(@RequestParam("file") MultipartFile file,
                          @RequestParam("userId") String userId,
                          HttpServletRequest request) {
        return AjaxResult.success(userService.updateUserAvatar(userId, file, request));
    }


    @ApiOperation("查询专家收入")
    @GetMapping("findExpertIncome")
    public AjaxResult findExpertIncome(HttpServletRequest request) {
        User loginUser = GetUserUtils.getLoginUser(request);
        return AjaxResult.success(userService.selectUserIncome(loginUser));
    }

    @ApiOperation("查询银行卡")
    @GetMapping("selectBankCard")
    public AjaxResult selectBankCard(HttpServletRequest request) {
        User loginUser = GetUserUtils.getLoginUser(request);
        BankCardTable bankCardTable = new BankCardTable();
        bankCardTable.setUserId(loginUser.getUserId());
        return AjaxResult.success(bankCardTableService.selectBankCard(bankCardTable));
    }

    @ApiOperation("添加银行卡")
    @PostMapping("insertBankCard")
    public AjaxResult insertBankCard(HttpServletRequest request, @RequestBody BankCardTable bankCardTable) {
        User loginUser = GetUserUtils.getLoginUser(request);
        bankCardTable.setUserId(loginUser.getUserId());
        return AjaxResult.success(bankCardTableService.insertBankCard(bankCardTable));
    }

    @ApiOperation("查询银行信息")
    @GetMapping("findBankInfo")
    public AjaxResult findBankInfo() {
        return AjaxResult.success(bankInfoService.selectBankInfoList(new BankInfo()));
    }

    @ApiOperation("查询专家评价")
    @GetMapping("getExpertEvaluate")
    public AjaxResult getExpertEvaluate(HttpServletRequest request) {
        User loginUser = GetUserUtils.getLoginUser(request);
        Evaluate evaluate = new Evaluate();
        evaluate.setToUserId(loginUser.getUserId());
        return AjaxResult.success(evaluateService.selectEvaluates(evaluate));
    }

    @ApiOperation("平台建议图片上传")
    @PostMapping("suggestionUpload")
    public AjaxResult suggestionUpload(@RequestParam("file") MultipartFile file,
                                   HttpServletRequest request) {
        User loginUser = GetUserUtils.getLoginUser(request);
        return AjaxResult.success(suggestionService.suggestionUpload(loginUser.getUserId(), file, request));
    }

    @ApiOperation("平台建议")
    @PostMapping("insertSuggestion")
    public AjaxResult insertSuggestion(HttpServletRequest request, @RequestBody Suggestion suggestion) {
        User loginUser = GetUserUtils.getLoginUser(request);
        suggestion.setUserId(loginUser.getUserId());
        return AjaxResult.success(suggestionService.insertSuggestion(suggestion));
    }

    @ApiOperation("添加医生")
    @PostMapping("insertDoctor")
    public AjaxResult insertDoctor(HttpServletRequest request, @RequestBody DoctorLibraryVO doctorLibrary) {
        User loginUser = GetUserUtils.getLoginUser(request);
        doctorLibrary.setUserId(loginUser.getUserId());
        return AjaxResult.success(doctorLibraryService.insertDoctorLibrary(doctorLibrary));
    }

    @ApiOperation("修改医生")
    @PostMapping("updateDoctor")
    public AjaxResult updateDoctor(HttpServletRequest request, @RequestBody DoctorLibraryVO doctorLibrary) {
        User loginUser = GetUserUtils.getLoginUser(request);
        doctorLibrary.setUserId(loginUser.getUserId());
        return AjaxResult.success(doctorLibraryService.updateDoctor(doctorLibrary));
    }

    @ApiOperation("查询医生库")
    @GetMapping("selectDoctorLibraryList")
    public AjaxResult selectDoctorLibraryList(HttpServletRequest request) {
        User loginUser = GetUserUtils.getLoginUser(request);
        DoctorLibrary doctorLibrary = new DoctorLibrary();
        doctorLibrary.setUserId(loginUser.getUserId());
        return AjaxResult.success(doctorLibraryService.selectDoctorLibrarys(doctorLibrary));
    }

    @ApiOperation("查询专家城市列表")
    @GetMapping("getUserCityList")
    public AjaxResult getUserCityList(HttpServletRequest request) {
        User loginUser = GetUserUtils.getLoginUser(request);
        return AjaxResult.success(userService.selectUserCity(loginUser));
    }

    @ApiOperation("查询专家疾病列表")
    @GetMapping("getExpertDisease")
    public AjaxResult getExpertDisease(HttpServletRequest request) {
        User loginUser = GetUserUtils.getLoginUser(request);
        return AjaxResult.success(userService.selectExpertDisease(loginUser));
    }

    @ApiOperation("查询城市列表")
    @GetMapping("getCityList")
    public AjaxResult getCityList() {
        City city = new City();
        return AjaxResult.success(cityService.selectCityList(city));
    }

    @ApiOperation("根据城市查询医院")
    @PostMapping("getHospital")
    public AjaxResult getHospital(@RequestBody Hospital hospital) {
        return AjaxResult.success(hospitalService.selectHospitalList(hospital));
    }

    @ApiOperation("删除医生")
    @PostMapping("delDoctor/{doctorIds}")
    public AjaxResult delDoctor(@PathVariable Long[] doctorIds) {
        return AjaxResult.success(doctorLibraryService.deleteDoctorLibraryByDoctorIds(doctorIds));
    }

    @ApiOperation("修改专家信息")
    @PostMapping("updateExpert")
    public AjaxResult updateExpert(@RequestBody UserVO userVO) {
        return AjaxResult.success(userService.updateExpert(userVO));
    }

    @ApiOperation("查询专家对应的病种")
    @GetMapping("selectUserByDisease")
    public AjaxResult selectUserByDisease(HttpServletRequest request) {
        User loginUser = GetUserUtils.getLoginUser(request);
        List<Disease> diseases = diseaseService.selectUserDisease(loginUser.getUserId());
        return AjaxResult.success(diseases);
    }

    @ApiOperation("添加问卷")
    @PostMapping("insertQuestionnaire")
    public AjaxResult insertQuestionnaire(HttpServletRequest request, @RequestBody List<Questionnaire> questionnaires) {
        User loginUser = GetUserUtils.getLoginUser(request);
        for (Questionnaire questionnaire : questionnaires) {
            questionnaire.setUserId(loginUser.getUserId());
            questionnaireService.insertQuestionnaire(questionnaire);
        }
        return AjaxResult.success();
    }

    @ApiOperation("修改专家密码")
    @PostMapping("/updateExpertPwd")
    public AjaxResult updateExpertPwd(HttpServletRequest request, @RequestBody ExpertPwd expertPwd) {
//        User loginUser = GetUserUtils.getLoginUser(request);
//        expertPwd.setUserId(loginUser.getUserId());
        return wxLoginService.updateExpertPwd(expertPwd);
    }

    @ApiOperation("专家提现申请")
    @PostMapping("/withdrawal")
    public AjaxResult withdrawal(HttpServletRequest request, @RequestBody WithdrawalTable withdrawalTable) {
        User loginUser = GetUserUtils.getLoginUser(request);
        withdrawalTable.setUserId(loginUser.getUserId());
        return userService.withdrawal(withdrawalTable);
    }

    @ApiOperation("查询提现规则")
    @GetMapping("/getDescriptionRule")
    public AjaxResult getDescriptionRule() {
        List<DescriptionRule> descriptionRules = descriptionRuleService.selectDescriptionRuleList(new DescriptionRule());
        if (!descriptionRules.isEmpty()) {
            return AjaxResult.success(descriptionRules.get(0));
        } else {
            return AjaxResult.error();
        }
    }

    @GetMapping("/callback")
    public String wechatCallbackExpert(
            @RequestParam("signature") String signature,
            @RequestParam("timestamp") String timestamp,
            @RequestParam("nonce") String nonce,
            @RequestParam("echostr") String echostr) {

        String token = "gthxcy15J4V2ACFC6zkmRAfJFBdiWeQ9"; // 跟微信后台配置的保持一致

        // 对 token, timestamp, nonce 三个参数进行字典序排序
        String[] arr = new String[] { token, timestamp, nonce };
        Arrays.sort(arr);
        StringBuilder sb = new StringBuilder();
        for (String s : arr) {
            sb.append(s);
        }

        // SHA1加密
        String sha1Str = Sha1Hex.sha1Hex(sb.toString());

        // 判断加密后的字符串和微信传过来的signature是否相等
        if (sha1Str.equals(signature)) {
            // 验证通过，返回echostr
            return echostr;
        }
        // 验证失败，返回空或错误信息
        return "error";
    }

    @GetMapping("/userCallback")
    public String wechatCallbackUser(
            @RequestParam("signature") String signature,
            @RequestParam("timestamp") String timestamp,
            @RequestParam("nonce") String nonce,
            @RequestParam("echostr") String echostr) {

        String token = "Crx8dU6W1ar0bg3KoxpmIchRyHfSQssv"; // 跟微信后台配置的保持一致

        // 对 token, timestamp, nonce 三个参数进行字典序排序
        String[] arr = new String[] { token, timestamp, nonce };
        Arrays.sort(arr);
        StringBuilder sb = new StringBuilder();
        for (String s : arr) {
            sb.append(s);
        }

        // SHA1加密
        String sha1Str = Sha1Hex.sha1Hex(sb.toString());

        // 判断加密后的字符串和微信传过来的signature是否相等
        if (sha1Str.equals(signature)) {
            // 验证通过，返回echostr
            return echostr;
        }
        // 验证失败，返回空或错误信息
        return "error";
    }

    @PostMapping("/callback")
    public String callbackExpert(HttpServletRequest request) {
        try {
            // 读取 XML 内容
            StringBuilder xmlBuilder = new StringBuilder();
            BufferedReader reader = request.getReader();
            String line;
            while ((line = reader.readLine()) != null) {
                xmlBuilder.append(line);
            }
            String xml = xmlBuilder.toString();
            log.info("接收到微信 XML：{}", xml);

            // 解析 XML
            Map<String, String> messageMap = parseXml(xml);
            String msgType = messageMap.get("MsgType");
            String event = messageMap.get("Event");
            String openId = messageMap.get("FromUserName");
            String eventKey = messageMap.get("EventKey");
            log.info("解析后的消息: {}", messageMap);

            if ("event".equals(msgType)) {
                if ("subscribe".equals(event)) {
                    // 关注
                    if (eventKey != null && eventKey.startsWith("qrscene_")) {
                        String userId = eventKey.replace("qrscene_", "");
                        userId = String.format("%06d", Integer.parseInt(userId));
                        log.info("扫码关注事件 - userId: {}, openId: {}", userId, openId);
                        UserVO userVO = userService.selectUserByUserId(userId);
                        User user = new User();
                        BeanUtils.copyProperties(userVO, user);
                        user.setServiceOpenId(openId);
                        userService.updateUser(user);
                    } else {
                        log.info("普通关注事件 - openId: {}", openId);
                    }
                } else if ("unsubscribe".equals(event)) {
                    // 取消关注
                    log.info("取消关注事件 - openId: {}", openId);
                    User user = userService.selectUserByServiceOpenId(openId);
                    // 清空绑定
                    userService.updateUserByServiceOpenId(user.getServiceOpenId(), user.getUserId());
                }
            }

            return "success"; // 必须返回 success
        } catch (Exception e) {
            log.error("处理微信回调失败", e);
            return "error";
        }
    }


    @PostMapping("/userCallback")
    public String callbackUser(HttpServletRequest request) {
        try {
            // 读取 XML 内容
            StringBuilder xmlBuilder = new StringBuilder();
            BufferedReader reader = request.getReader();
            String line;
            while ((line = reader.readLine()) != null) {
                xmlBuilder.append(line);
            }
            String xml = xmlBuilder.toString();
            log.info("接收到微信 XML：{}", xml);

            // 解析 XML
            Map<String, String> messageMap = parseXml(xml);
            String msgType = messageMap.get("MsgType");
            String event = messageMap.get("Event");
            String openId = messageMap.get("FromUserName");
            String eventKey = messageMap.get("EventKey");
            log.info(messageMap.toString());

            if ("event".equals(msgType) && "subscribe".equals(event)) {
                if (eventKey != null && eventKey.startsWith("qrscene_")) {
                    String userId = eventKey.replace("qrscene_", "");
                    userId = String.format("%06d", Integer.parseInt(userId));
                    log.info("扫码关注事件 - userId: {}, openId: {}", userId, openId);
                    // 绑定 openId 和 userId
                    UserVO userVO = userService.selectUserByUserId(userId);
                    User user = new User();
                    BeanUtils.copyProperties(userVO, user);
                    user.setServiceOpenId(openId);
                    userService.updateUser(user);
                } else {
                    log.info("普通关注事件 - openId: {}", openId);
                }
            }

            return "success"; // 必须返回 success
        } catch (Exception e) {
            log.error("处理微信回调失败", e);
            return "error";
        }
    }


    @ApiOperation("获取专家端服务号二维码")
    @GetMapping("/getQeCodeExpert")
    public AjaxResult getQeCodeExpert(HttpServletRequest request) throws Exception {
        User loginUser = GetUserUtils.getLoginUser(request);
        String result;
        UserVO userVO = userService.selectUserByUserId(loginUser.getUserId());
        User user = new User();
        BeanUtils.copyProperties(userVO, user);
        String serviceOpenId = user.getServiceOpenId();
        if (serviceOpenId == null) {
            result = WeChatQrCodeUtil.generateTempQrCodeUrl(loginUser.getUserId());
        } else {
            result = "1";
        }
        return AjaxResult.success(result);
    }

    @ApiOperation("获取用户端服务号二维码")
    @GetMapping("/getQeCodeUser")
    public AjaxResult getQeCodeUser(HttpServletRequest request) throws Exception {
        log.info("==================获取用户服务号二维码 - userId: {}");
        User loginUser = GetUserUtils.getLoginUser(request);
        UserVO userVO = userService.selectUserByUserId(loginUser.getUserId());
        User user = new User();
        BeanUtils.copyProperties(userVO, user);
        String serviceOpenId = user.getServiceOpenId();
        String result;
        log.info("===========================获取用户服务号二维码 - userId: {}, openId: {}", loginUser.getUserId(), serviceOpenId);
        if ("".equals(serviceOpenId) || serviceOpenId == null) {
            result = WeChatQrCodeUtil.generateTempQrCodeUrlUser(loginUser.getUserId());
        } else {
            result = "1";
        }
        return AjaxResult.success(result);
    }

    public Map<String, String> parseXml(String xml) throws Exception {
        Map<String, String> map = new HashMap<>();
        InputStream inputStream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
        SAXReader reader = new SAXReader();
        Document document = reader.read(inputStream);
        Element root = document.getRootElement();
        List<Element> elements = root.elements();
        for (Element element : elements) {
            map.put(element.getName(), element.getText());
        }
        inputStream.close();
        return map;
    }


}
